/*Author: Seungbeom Ma
 *SJSU 
 * DATE: NOV 16
 * */

package tool.math;

import java.text.DecimalFormat;
import java.util.Random;

import android.util.Log;

public class MathEquations {
	// Calculate based on random number
	// @parm  Process_list ID;Amount
	// @return String type average
	public String Gaussian_AVG(String Process_List){
		Log.d("MathEquations", "Running MathEquations on local device");
		String TaskID = "";
		String Amount_of_Task = "";
		String []RequestedTasks  =  Process_List.split(":");
		Random random = new Random(); 
		DecimalFormat df = new DecimalFormat("#.###");
		String Returning_Result = null;
		double y = 0.0;
        for(int i = 0 ; i < RequestedTasks.length ; i++){
        	String [] IDandTask = RequestedTasks[i].split(";");
        	TaskID = IDandTask[0];
        	Amount_of_Task = IDandTask[1];
          	int counter = Integer.parseInt(Amount_of_Task);
          	
          	for(int ii = 1 ; ii <= counter; ii ++ )
          	{
          	       double z  =  random.nextInt(800)+1;
          	       double mu    =  random.nextInt(500)+1;
          	       double sigma =   random.nextInt(900)+1;
          	   //  Result += Phi(z, mu, sigma)+":";
          	       Phi(z, mu, sigma);
          	      //  y += Phi(Math.tan(Math.tan(Math.tan(z))), Math.tan(Math.tan(mu)), Math.tan(Math.tan(sigma)));
          	     y += Phi(Math.tan(Math.tan(Math.tan(z))), Math.tan(Math.tan(mu)), Math.tan(Math.tan(sigma)))/ PhiInverse(Math.tan( Math.tan( Math.tan( Math.tan(PhiInverse(y))))));
          	       PhiInverse(y);
          	}
       
          	y /= counter;
          	
          	 if(Returning_Result==null){
          		
             	Returning_Result = TaskID +";"+ df.format(y);
             }
             else{
            	df.format(y);
             	Returning_Result = Returning_Result+":" + TaskID +";"+ df.format(y);
             }
        }
        return Returning_Result;
	}
	//
	public String Gaussian_AVG_Constant(String Process_List){
		Log.d("MathEquations", "Running MathEquations with Constant number");
		String TaskID = "";
		String Amount_of_Task = "";
		String []RequestedTasks  =  Process_List.split(":");
		Random random = new Random(); 
		DecimalFormat df = new DecimalFormat("#.###");
		String Returning_Result = null;
		double y = 0.0;
		double q = 0.0;
        for(int i = 0 ; i < RequestedTasks.length ; i++){
        	String [] IDandTask = RequestedTasks[i].split(";");
        	TaskID = IDandTask[0];
        	Amount_of_Task = IDandTask[1];
          	int counter = Integer.parseInt(Amount_of_Task);
          	
          	for(int ii = 1 ; ii <= counter; ii ++ )
          	{
//          	       double z  =  333331;
//          	       double mu    =  50111112;
//          	       double sigma =  911111;  
       	       double z  =   911111;
       	       double mu    =  4329149;
       	       double sigma =   3;
          	       Phi(z, mu, sigma);
          	       y += Phi(Math.tan(Math.tan(Math.tan(z))), Math.tan(Math.tan(mu)), Math.tan(Math.tan(sigma)))/ PhiInverse(Math.tan( Math.tan( Math.tan( Math.tan(PhiInverse(y))))));
          	    // y += Phi(z, mu, sigma);
          	       //PhiInverse(y);
          	    
          	}
          	y /= counter;
          	
          	 if(Returning_Result==null){
          		
             	Returning_Result = TaskID +";"+ df.format(y);
             }
             else{
            	df.format(y);
             	Returning_Result = Returning_Result+":" + TaskID +";"+ df.format(y);
             }
        }
        return Returning_Result;
	}
	
	
	// GUS Helper function
    public static double phi(double x) {
        return Math.exp(-x*x / 2) / Math.sqrt(2 * Math.PI);
    }
    public static double phi(double x, double mu, double sigma) {
        return phi((x - mu) / sigma) / sigma;
    }

    // return Phi(z) = standard Gaussian cdf using Taylor approximation
    public static double Phi(double z) {
        if (z < -8.0) return 0.0;
        if (z >  8.0) return 1.0;
        double sum = 0.0, term = z;
        for (int i = 3; sum + term != sum; i += 2) {
            sum  = sum + term;
            term = term * z * z / i;
        }
        return 0.5 + sum * phi(z);
    }

    // return Phi(z, mu, sigma) = Gaussian cdf with mean mu and stddev sigma
    public double Phi(double z, double mu, double sigma) {
        return Phi((z - mu) / sigma);
    } 

    // Compute z such that Phi(z) = y via bisection search
    public  double PhiInverse(double y) {
        return PhiInverse(y, .00000001, -8, 8);
    } 

    // bisection search
    private  double PhiInverse(double y, double delta, double lo, double hi) {
        double mid = lo + (hi - lo) / 2;
        if (hi - lo < delta) {
        	return mid;
        }
        if (Phi(mid) > y) return PhiInverse(y, delta, lo, mid);
        else              return PhiInverse(y, delta, mid, hi);
    }
    
}
